home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 176-200 / scopedisk192 / unzipv3.1 / unzip_030.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  24KB  |  896 lines

  1. #define M030
  2.  
  3. /*
  4.  * Copyright 1989 Samuel H. Smith;  All rights reserved
  5.  *
  6.  * Do not distribute modified versions without my permission.
  7.  * Do not remove or alter this notice or any other copyright notice.
  8.  * If you use this in your own program you must distribute source code.
  9.  * Do not use any of this in a commercial product.
  10.  *
  11.  */
  12.  
  13. /*
  14.  * UnZip - A simple zipfile extract utility
  15.  *
  16.  * Compile-time definitions:
  17.  * See the Makefile for details, explanations, and all the current
  18.  * system makerules.
  19.  *
  20.  * If you have to add a new one for YOUR system, please forward the
  21.  * new Makefile to kirsch@usasoc.soc.mil for distribution.
  22.  * Be SURE to give FULL details on your system (hardware, OS, versions,
  23.  * processor, whatever) that made it unique.
  24.  *
  25.  * REVISION HISTORY : See history.307 (or whatever current version is)
  26.  *
  27.  */
  28.  
  29. #include "unzip.h"
  30. #include "zip_proto.i"
  31.             /* v3.05 a BUNCH of ifdefs, etc.
  32.              * split out to reduce file size.
  33.              * David Kirschbaum
  34.              */
  35.  
  36. char *fnames[2] = { /* default filenames vector */
  37.     "*",
  38.     NULL
  39. };
  40. char **fnv = &fnames[0];
  41.  
  42. int tflag;      /* -t: test */
  43. int vflag;      /* -v: view directory */
  44. int cflag;      /* -c: output to stdout (JC) */
  45. int aflag;      /* -a: do ascii to ebcdic translation 2.0f */
  46.                 /*     OR <cr><nl> to <nl> conversion  */
  47. int mflag;    /* -m: map member filenames to lower case v2.0j */
  48. int CR_flag = 0; /* When last char of buffer == CR */
  49.  
  50. int members;
  51. longint csize;
  52. longint ucsize;
  53. longint tot_csize;
  54. longint tot_ucsize;
  55.  
  56.  
  57. /* ----------------------------------------------------------- */
  58. /*
  59.  * shrink/reduce working storage
  60.  *
  61.  */
  62.  
  63. int factor;
  64. /* really need only 256, but prefix_of, which shares the same
  65.    storage, is just over 16K */
  66. byte __huge followers[257][64];    /* also lzw prefix_of, s-f lit_nodes */
  67. byte __huge Slen[256];
  68.  
  69. typedef short hsize_array_integer[hsize+1]; /* was used for prefix_of */
  70. typedef byte hsize_array_byte[hsize+1];
  71.  
  72. short *prefix_of = (short *) followers; /* share reduce/shrink storage */
  73.  
  74. #ifdef    AMIGA
  75. long dummy_1_to_ensure_alignment;
  76. #endif
  77. hsize_array_byte suffix_of;     /* also s-f length_nodes */
  78.  
  79. #ifdef    AMIGA
  80. long dummy_2_to_ensure_alignment;
  81. #endif
  82. hsize_array_byte stack;         /* also s-f distance_nodes */
  83.  
  84. int codesize;
  85. int maxcode;
  86. int free_ent;
  87. int maxcodemax;
  88. int offset;
  89. int sizex;
  90.  
  91. /* Code now begins ( .. once more into the Valley of Death.. ) */
  92.  
  93.  
  94. #ifdef NOTINT16     /* v2.0c */
  95. UWORD makeword(b)
  96. byte * b;
  97.  /* convert Intel style 'short' integer to non-Intel non-16-bit
  98.   * host format
  99.   */
  100. {
  101. /*
  102.     return  ( ((UWORD) (b[1]) << 8)
  103.             | (UWORD) (b[0])
  104.             );
  105. */
  106.     return  ( ( b[1] << 8)
  107.             | b[0]
  108.             );
  109. }
  110.  
  111. longint makelong(sig)
  112. byte *sig;
  113.  /* convert intel style 'long' variable to non-Intel non-16-bit
  114.   * host format
  115.   */
  116. {
  117.     return ( ((longint) sig[3]) << 24)
  118.           + ( ((longint) sig[2]) << 16)
  119.           + ( ((longint) sig[1]) << 8)
  120.           +   ((longint)  sig[0]) ;
  121. }
  122. #endif  /* NOTINT16 */
  123.  
  124. #ifdef HIGH_LOW
  125.  
  126. void swap_bytes(UWORD *);
  127. void swap_lbytes(longint *);
  128.  
  129. void swap_bytes(wordp)
  130. UWORD *wordp;
  131.  /* convert Intel style 'short int' variable to host format */
  132. {
  133.     char *charp = (char *) wordp;
  134.     char temp;
  135.  
  136.     temp = charp[0];
  137.     charp[0] = charp[1];
  138.     charp[1] = temp;
  139. }
  140.  
  141. void swap_lbytes(longp)
  142. longint *longp;
  143.  /* convert intel style 'long' variable to host format */
  144. {
  145.     char *charp = (char *) longp;
  146.     char temp[4];
  147.  
  148.     temp[3] = charp[0];
  149.     temp[2] = charp[1];
  150.     temp[1] = charp[2];
  151.     temp[0] = charp[3];
  152.  
  153.     charp[0] = temp[0];
  154.     charp[1] = temp[1];
  155.     charp[2] = temp[2];
  156.     charp[3] = temp[3];
  157. }
  158.  
  159. #endif /* HIGH_LOW */
  160. /* ----------------------------------------------------------- */
  161.  
  162. #include "file_io.c"        /* v3.05 file-related vars, functions */
  163.  
  164. #include "unreduce.c"        /* v3.05 */
  165.  
  166. #include "unshrink.c"        /* v3.05 */
  167.  
  168. #include "unimplod.c"        /* v3.05 */
  169.  
  170. /* ---------------------------------------------------------- */
  171.  
  172. /*
  173.  Length  Method   Size  Ratio   Date    Time   CRC-32    Name
  174.  ------  ------   ----- -----   ----    ----   ------    ----
  175.   44004  Implode  13041  71%  11-02-89  19:34  88420727  DIFF3.C
  176.  */
  177.  
  178. void dir_member()
  179. {
  180.     char *method;
  181.     int ratio;
  182.     int yr, mo, dy, hh, mm;
  183.  
  184.     yr = (((lrec.last_mod_file_date >> 9) & 0x7f) + 80);
  185.     mo = ((lrec.last_mod_file_date >> 5) & 0x0f);
  186.     dy = (lrec.last_mod_file_date & 0x1f);
  187.  
  188.     hh = ((lrec.last_mod_file_time >> 11) & 0x1f);
  189.     mm = ((lrec.last_mod_file_time >> 5) & 0x3f);
  190.  
  191.     switch (lrec.compression_method)  {
  192.     case 0:
  193.         method = "Stored";
  194.         break;
  195.     case 1:
  196.         method = "Shrunk";
  197.         break;
  198.     case 2:
  199.     case 3:
  200.     case 4:
  201.     case 5:
  202.         method = "Reduced";
  203.         break;
  204.     case 6:
  205.         method = "Implode";
  206.         break;
  207.     }
  208.  
  209.     if (ucsize != 0)  {
  210.         ratio = (int) ((1000L * (ucsize - csize)) / ucsize);
  211.         if ((ratio % 10) >= 5)
  212.             ratio += 10;
  213.     }
  214.     else
  215.         ratio = 0;  /* can .zip contain 0-size file? */
  216.  
  217. #ifdef NOTINT16     /* v2.0c */
  218.     printf("%7ld  %-7s%7ld %3d%%  %02d-%02d-%02d  %02d:%02d  \
  219. %08lx  %s\n", ucsize, method, csize,
  220.         ratio / 10, mo, dy, yr, hh, mm,
  221.         lrec.crc32, filename);
  222. #else   /* !NOTINT16 */
  223.     printf("%7ld  %-7s%7ld %3d%%  %02d-%02d-%02d  %02d:%02d  \
  224. %08lx  %s\n", ucsize, method, csize,
  225.         ratio / 10, mo, dy, yr, hh, mm,
  226.         LONGI(lrec.crc32), filename);
  227. #endif  /* NOTINT16 */
  228.     tot_ucsize += ucsize;
  229.     tot_csize += csize;
  230.     ++members;
  231. }
  232.  
  233. /* ---------------------------------------------------------- */
  234.  
  235. void skip_member()
  236. {
  237.     register long pos;
  238.     long endbuf;
  239.     int offset;
  240.  
  241.     endbuf = lseek(zipfd, 0L, SEEK_CUR);    /* 1st byte beyond inbuf */
  242.     pos = endbuf - incnt;                   /* 1st compressed byte */
  243.     pos += csize;                           /* next header signature */
  244.     if (pos < endbuf)  {
  245.         incnt -= csize;
  246.         inptr += csize;
  247.     }
  248.     else  {
  249.         offset = pos % BSIZE;               /* offset within block */
  250.         pos = (pos / BSIZE) * BSIZE;        /* block start */
  251.         lseek(zipfd, pos, SEEK_SET);
  252.         incnt = read(zipfd, inbuf, INBUFSIZ);
  253.         incnt -= offset;
  254.         inptr = inbuf + offset;
  255.     }
  256. }
  257.  
  258. /* ---------------------------------------------------------- */
  259.  
  260. void extract_member()
  261. {
  262.         UWORD     b;
  263. /* for test reasons */
  264.  
  265.     bits_left = 0;
  266.     bitbuf = 0;
  267.     outpos = 0L;
  268.     outcnt = 0;
  269.     outptr = outbuf;
  270.     zipeof = 0;
  271.     crc32val = 0xFFFFFFFFL;
  272.  
  273.     zmemset(outbuf, 0, OUTBUFSIZ);
  274.     if (aflag)                          /* if we have scratchpad.. v2.0g */
  275.         zmemset(outout, 0, OUTBUFSIZ);  /* ..clear it out v2.0g */
  276.       
  277.     if (tflag)
  278.         fprintf(stderr, "Testing: %-12s ", filename);
  279.     else {
  280.         if(!mapped_name())    /* member name conversion failed  v2.0j */
  281.         exit(1);        /* choke and die v2.0j */
  282.  
  283.         /* create the output file with READ and WRITE permissions */
  284.         if (create_output_file())
  285.             return; /* was exit(1); */
  286.     }
  287.     switch (lrec.compression_method) {
  288.  
  289.     case 0: {   /* stored */
  290.             if (!tflag)
  291.                 fprintf(stderr, " Extracting: %-12s ", filename);
  292.             if (cflag) fprintf(stderr, "\n");
  293.             while (ReadByte(&b))
  294.                 OUTB(b);
  295.         }
  296.         break;
  297.  
  298.     case 1: {       /* shrunk */
  299.             if (!tflag)
  300.                 fprintf(stderr, "UnShrinking: %-12s ", filename);
  301.             if (cflag) fprintf(stderr, "\n");
  302.             unShrink();
  303.         }
  304.         break;
  305.  
  306.     case 2:
  307.     case 3:
  308.     case 4:
  309.     case 5: {
  310.             if (!tflag)
  311.                 fprintf(stderr, "  Expanding: %-12s ", filename);
  312.             if (cflag) fprintf(stderr, "\n");
  313.             unReduce();
  314.         }
  315.         break;
  316.  
  317.     case 6: {
  318.             if (!tflag)
  319.                 fprintf(stderr, "  Exploding: %-12s ", filename);
  320.             if (cflag) fprintf(stderr, "\n");
  321.             unImplode();
  322.         }
  323.         break;
  324.  
  325.     default:
  326.         fprintf(stderr, "Unknown compression method.");
  327.     }
  328.  
  329.     /* write the last partial buffer, if any */
  330.     FlushOutput ();
  331.  
  332.     if (!tflag)  {
  333. #ifndef UNIX
  334.         /* set output file date and time */
  335.         set_file_time();
  336.         close(outfd);
  337. #else
  338.         close(outfd);
  339.         /* set output file date and time */
  340.         set_file_time();
  341. #endif
  342.     }
  343.  
  344.     crc32val = ~crc32val;
  345. #ifdef NOTINT16     /* v2.0c */
  346.     if (crc32val != lrec.crc32)
  347.         fprintf(stderr, " Bad CRC %08lx  (should be %08lx)", crc32val,
  348.             lrec.crc32);
  349. #else   /* !NOTINT16 */
  350.     if (crc32val != LONGI(lrec.crc32))
  351.         fprintf(stderr, " Bad CRC %08lx  (should be %08lx)", crc32val,
  352.             LONGI(lrec.crc32));
  353. #endif  /* NOTINT16 */
  354.  
  355.     else if (tflag)
  356.         fprintf(stderr, " OK");
  357.  
  358.     fprintf(stderr, "\n");
  359. }
  360.  
  361.  
  362. /* ---------------------------------------------------------- */
  363.  
  364. void get_string(len, s)
  365. int len;
  366. char *s;
  367. {
  368.     readbuf(zipfd, s, len);
  369.     s[len] = 0;
  370.  
  371. #ifdef EBCDIC           /* translate the filename to ebcdic */
  372.     a_to_e( s );        /* A.B.  03/21/90                   */
  373. #endif
  374. }
  375.  
  376.  
  377. /* ---------------------------------------------------------- */
  378.  
  379. void process_local_file_header(fnamev)
  380. char **fnamev;
  381. {
  382.     int extracted;
  383. #ifdef NOTINT16     /* v2.0c */
  384.     local_byte_header brec;
  385. #endif
  386.  
  387. #ifndef NOTINT16    /* v2.0c */
  388.     readbuf(zipfd, (char *) &lrec, sizeof(lrec));   /* v2.0b */
  389. #else   /* NOTINT16 */
  390.     readbuf(zipfd, (char *) &brec, sizeof(brec));
  391.  
  392.     lrec.version_needed_to_extract =
  393.         makeword(brec.version_needed_to_extract);
  394.     lrec.general_purpose_bit_flag =
  395.         makeword(brec.general_purpose_bit_flag);
  396.     lrec.compression_method =
  397.         makeword(brec.compression_method);
  398.     lrec.last_mod_file_time =
  399.         makeword(brec.last_mod_file_time);
  400.     lrec.last_mod_file_date =
  401.         makeword(brec.last_mod_file_date);
  402.     lrec.crc32 =
  403.         makelong(brec.crc32);
  404.     lrec.compressed_size =
  405.         makelong(brec.compressed_size);
  406.     lrec.uncompressed_size =
  407.         makelong(brec.uncompressed_size);
  408.     lrec.filename_length =
  409.         makeword(brec.filename_length);
  410.     lrec.extra_field_length =
  411.         makeword(brec.extra_field_length);
  412. #endif  /* NOTINT16 */
  413.  
  414. #ifdef HIGH_LOW
  415.     swap_bytes(&lrec.filename_length);
  416.     swap_bytes(&lrec.extra_field_length);
  417.     swap_lbytes(LONGIP(lrec.compressed_size));
  418.     swap_lbytes(LONGIP(lrec.uncompressed_size));
  419.     swap_bytes(&lrec.compression_method);
  420.     swap_bytes(&lrec.version_needed_to_extract);
  421.     swap_bytes(&lrec.general_purpose_bit_flag);
  422.     swap_bytes(&lrec.last_mod_file_time);
  423.     swap_bytes(&lrec.last_mod_file_date);
  424.     swap_lbytes(LONGIP(lrec.crc32));
  425. #endif  /* HIGH_LOW */
  426.  
  427. #ifdef NOTINT16     /* v2.0c */
  428.     csize = lrec.compressed_size;
  429.     ucsize = lrec.uncompressed_size;
  430. #else   /* !NOTINT16 */
  431.     csize = LONGI(lrec.compressed_size);
  432.     ucsize = LONGI(lrec.uncompressed_size);
  433. #endif  /* NOTINT16 */
  434.  
  435.     get_string(lrec.filename_length, filename);
  436.     get_string(lrec.extra_field_length, extra);
  437.  
  438.     extracted = 0;
  439.     for (--fnamev; *++fnamev; )  {
  440.         if (match(filename, *fnamev))  {
  441.             if (vflag)
  442.                 dir_member();
  443.             else  {
  444.                 extract_member();
  445.                 extracted = 1;
  446.             }
  447.             break;
  448.         }
  449.     }
  450.     if (!extracted)
  451.         skip_member();
  452. }
  453.  
  454.  
  455. /* ---------------------------------------------------------- */
  456.  
  457. void process_central_file_header()
  458. {
  459.     central_directory_file_header rec;
  460.     char filename[STRSIZ];
  461.     char extra[STRSIZ];
  462. /*  char comment[STRSIZ]; v2.0b using global comment so we can display it */
  463.  
  464. #ifdef NOTINT16     /* v2.0c */
  465.     central_directory_byte_header byterec;
  466. #endif
  467.  
  468. #ifndef NOTINT16    /* v2.0c */
  469.     readbuf(zipfd, (char *) &rec, sizeof(rec)); /* v2.0b */
  470. #else   /* NOTINT16 */
  471.     readbuf(zipfd, (char *) &byterec, sizeof(byterec) );        /* v2.0c */
  472.  
  473.     rec.version_made_by =
  474.         makeword(byterec.version_made_by);
  475.     rec.version_needed_to_extract =
  476.         makeword(byterec.version_needed_to_extract);
  477.     rec.general_purpose_bit_flag =
  478.         makeword(byterec.general_purpose_bit_flag);
  479.     rec.compression_method =
  480.         makeword(byterec.compression_method);
  481.     rec.last_mod_file_time =
  482.         makeword(byterec.last_mod_file_time);
  483.     rec.last_mod_file_date =
  484.         makeword(byterec.last_mod_file_date);
  485.     rec.crc32 =
  486.         makelong(byterec.crc32);
  487.     rec.compressed_size =
  488.         makelong(byterec.compressed_size);
  489.     rec.uncompressed_size =
  490.         makelong(byterec.uncompressed_size);
  491.     rec.filename_length =
  492.         makeword(byterec.filename_length);
  493.     rec.extra_field_length =
  494.         makeword(byterec.extra_field_length);
  495.     rec.file_comment_length =
  496.         makeword(byterec.file_comment_length);
  497.     rec.disk_number_start =
  498.         makeword(byterec.disk_number_start);
  499.     rec.internal_file_attributes =
  500.         makeword(byterec.internal_file_attributes);
  501.     rec.external_file_attributes =
  502.         makeword(byterec.external_file_attributes);
  503.     rec.relative_offset_local_header =
  504.         makelong(byterec.relative_offset_local_header);
  505. #endif  /* NOTINT16 */
  506.  
  507. #ifdef HIGH_LOW
  508.     swap_bytes(&rec.filename_length);
  509.     swap_bytes(&rec.extra_field_length);
  510.     swap_bytes(&rec.file_comment_length);
  511. #endif
  512.  
  513.     get_string(rec.filename_length, filename);
  514.     get_string(rec.extra_field_length, extra);
  515.     get_string(rec.file_comment_length, comment);
  516. }
  517.  
  518.  
  519. /* ---------------------------------------------------------- */
  520.  
  521. void process_end_central_dir()
  522. {
  523.     end_central_dir_record rec;
  524. /*  char comment[STRSIZ]; v2.0b made global */
  525.  
  526. #ifdef NOTINT16     /* v2.0c */
  527.     end_central_byte_record byterec;
  528. #endif
  529.  
  530. #ifndef NOTINT16    /* v2.0c */
  531.     readbuf(zipfd, (char *) &rec, sizeof(rec)); /* v2.0b */
  532. #else   /* NOTINT16 */
  533.     readbuf(zipfd, (char *) &byterec, sizeof(byterec) );
  534.  
  535.     rec.number_this_disk =
  536.         makeword(byterec.number_this_disk);
  537.     rec.number_disk_with_start_central_directory =
  538.         makeword(byterec.number_disk_with_start_central_directory);
  539.     rec.total_entries_central_dir_on_this_disk =
  540.         makeword(byterec.total_entries_central_dir_on_this_disk);
  541.     rec.total_entries_central_dir =
  542.         makeword(byterec.total_entries_central_dir);
  543.     rec.size_central_directory =
  544.         makelong(byterec.size_central_directory);
  545.     rec.offset_start_central_directory =
  546.         makelong(byterec.offset_start_central_directory);
  547.     rec.zipfile_comment_length =
  548.         makeword(byterec.zipfile_comment_length);
  549. #endif  /* NOTINT16 */
  550.  
  551. #ifdef HIGH_LOW
  552.     swap_bytes(&rec.zipfile_comment_length);
  553. #endif
  554.  
  555.     /* There seems to be no limit to the zipfile
  556.        comment length.  Some zipfiles have comments
  557.        longer than 256 bytes.  Currently no use is
  558.        made of the comment anyway.
  559.      */
  560. /* #if 0
  561.  * v2.0b Enabling comment display
  562.  */
  563.     get_string(rec.zipfile_comment_length, comment);
  564. /* #endif */
  565. }
  566.  
  567.  
  568. /* ---------------------------------------------------------- */
  569.  
  570. void process_headers()
  571. {
  572.     int ratio;
  573.     long sig;
  574.  
  575. #ifdef NOTINT16     /* v2.0c */
  576.     byte sigbyte[4];
  577. #endif
  578.  
  579.     if (vflag)  {
  580.         members = 0;
  581.         tot_ucsize = tot_csize = 0;
  582.         printf("\n Length  Method   Size  Ratio   Date    Time   \
  583. CRC-32    Name\n ------  ------   ----- -----   ----    ----   ------    \
  584. ----\n");
  585.     }
  586.  
  587.     while (1) {
  588. #ifdef NOTINT16     /* v2.0c */
  589.     if (readbuf(zipfd, (char *) sigbyte, 4) != 4)
  590. #else   /* !NOTINT16 */
  591.     if (readbuf(zipfd, (char *) &sig, sizeof(sig)) != sizeof(sig))
  592. #endif  /* NOTINT16 */
  593.         return;
  594.  
  595. #ifdef NOTINT16     /* v2.0c */
  596.         sig = makelong(sigbyte);
  597. #endif
  598.  
  599. #ifdef HIGH_LOW
  600.         swap_lbytes(&sig);
  601. #endif
  602.  
  603.         if (sig == LOCAL_FILE_HEADER_SIGNATURE)
  604.             process_local_file_header(fnv);
  605.         else if (sig == CENTRAL_FILE_HEADER_SIGNATURE)
  606.             process_central_file_header();
  607.         else if (sig == END_CENTRAL_DIR_SIGNATURE) {
  608.             process_end_central_dir();
  609.             break;
  610.         }
  611.         else {
  612.             fprintf(stderr, "Invalid Zipfile Header\n");
  613.             return;
  614.         }
  615.     }
  616.     if (vflag)  {
  617.         if (tot_ucsize != 0)  {
  618.             ratio = (int) ((1000L * (tot_ucsize-tot_csize))
  619.                     / tot_ucsize);
  620.             if ((ratio % 10) >= 5)
  621.                 ratio += 10;
  622.         }
  623.         else
  624.             ratio = 0;
  625.         printf(" ------          ------  \
  626. ---                             -------\n\
  627. %7ld         %7ld %3d%%                             %7d\n",
  628.         tot_ucsize, tot_csize, ratio / 10, members);
  629.  
  630.         if( comment[0] )                /* v2.0b */
  631.             printf("%s\n",comment);     /* v2.0b */
  632.     }
  633. }
  634.  
  635.  
  636. /* ---------------------------------------------------------- */
  637. /* v3.04 Patch to enable processing of self-extracting ".EXE"
  638.  * (and other) files that might have weird junk before the first
  639.  * actual file member.
  640.  * I don't THINK anyone'll have problems with this .. but just in case,
  641.  * you can disable the entire mess by enabling the "NOSKIP" ifdef.
  642.  * (up near code top).
  643.  * Thanks to Warner Losh for this patch.
  644.  */
  645. #ifndef NOSKIP
  646. void skip_to_signature()
  647. {
  648.     static char pk[] = "PK";
  649.     int i, nread;
  650.     unsigned char ch;
  651.     extern int errno;
  652.     
  653.     errno = 0;            /* Be sure we start with 0 */
  654.     do {
  655.         /*
  656.          * Search for "PK"
  657.          */
  658.         i = 0;
  659.         while ((nread = read (zipfd, &ch, 1)) && i < 2) {
  660.             if (ch == pk[i]) {
  661.                 i++;
  662.             }
  663.             else {
  664.                 if (ch == pk[0])
  665.                     i = 1;
  666.                 else
  667.                     i = 0;
  668.             }
  669.         }
  670.     if (errno || nread==0) {    /* read err or EOF */
  671.         fprintf(stderr, "Unable to find a valid header signature. Aborting.\n");
  672.         exit (2);
  673.     }
  674.     } while (ch > 20);
  675.  
  676.     /*
  677.      * We have now read 3 characters too many, so we backup.
  678.      */
  679.     lseek (zipfd, -3L, SEEK_CUR);
  680. }
  681. #endif        /* NOSKIP */
  682.  
  683.  
  684. void process_zipfile()
  685. {
  686.     /*
  687.      * open the zipfile for reading and in BINARY mode to prevent cr/lf
  688.      * translation, which would corrupt the bitstreams
  689.      */
  690.  
  691.     if (open_input_file())
  692.         exit(1);
  693.  
  694. #ifndef NOSKIP        /* v3.03 */
  695.     skip_to_signature();    /* read up to first "PK%" v3.03 */
  696. #endif
  697.     process_headers();
  698.  
  699.     close(zipfd);
  700. }
  701.  
  702. /* ---------------------------------------------------------- */
  703.  
  704. void usage()        /* v2.0j */
  705. {
  706.  
  707. #ifdef EBCDIC                              /* A.B. 03/20/90   */
  708.   char *astring = "-a  ascii to ebcdic conversion";
  709. #else
  710.   char *astring = "-a  convert to unix textfile format (CR LF => LF)";    /* v3.04 */
  711. #endif
  712.  
  713. fprintf(stderr, "\n%s\nCourtesy of:  S.H.Smith  and  The Tool Shop BBS,  (602) 279-2673.\n\n",VERSION);
  714. fprintf(stderr, "Usage:  unzip [-tcamv] file[.zip] [filespec...]\n\
  715.   -t  test member files\n\
  716.   -c  output to stdout\n\
  717.   %s\n\
  718.   -m  map extracted filenames to lowercase\n\
  719.   -v  view directory\n",astring);
  720.     exit(1);
  721. }
  722.  
  723. /* ---------------------------------------------------------- */
  724.  
  725. /*
  726.  * main program
  727.  *
  728.  */
  729.  
  730. void main(argc, argv)
  731. int argc;
  732. char **argv;
  733. {
  734.     char *s;
  735.     int c;
  736. #ifndef    AMIGA
  737.     struct stat statbuf;        /* v3.03 */
  738. #endif    /* AMIGA */
  739.  
  740. #ifdef M030
  741.  
  742. #include <exec/types.h>
  743. #include <exec/execbase.h>
  744.  struct ExecBase **execbaseptr=(struct ExecBase **)4L;
  745.  UWORD cpuid;
  746.  struct ExecBase *execbase;
  747.  
  748.  execbase = *execbaseptr;
  749.  cpuid = execbase->AttnFlags;
  750.  if (!(cpuid & AFF_68020))
  751.   {
  752.    printf("You need a 68020 to run this program\n");
  753.    exit(0);
  754.   }
  755. #endif
  756.  
  757. #ifdef DEBUG_STRUC                      /* v2.0e */
  758. printf("local_file_header size: %X\n",
  759.     sizeof(struct local_file_header) );
  760. printf("local_byte_header size: %X\n",
  761.     sizeof(struct local_byte_header) );
  762.  
  763. printf("central directory header size: %X\n",
  764.     sizeof(struct central_directory_file_header) );
  765. printf("central directory byte header size: %X\n",
  766.     sizeof(struct central_directory_byte_header) );
  767.  
  768. printf("end central dir record size: %X\n",
  769.     sizeof(struct end_central_dir_record) );
  770. printf("end central dir byte record size: %X\n",
  771.     sizeof(struct end_central_byte_record) );
  772. #endif
  773.  
  774.     while (--argc > 0 && (*++argv)[0] == '-')  {
  775.         s = argv[0] + 1;
  776. #ifndef __TURBOC__
  777.         while (c = *s++)  {
  778. #else
  779.         while ((c = *s++) != '\0') {      /* v2.0b */
  780. #endif
  781.  
  782. /* Something is SERIOUSLY wrong with my host's tolower() function! */
  783. /* #ifndef BSD */
  784. /*            switch (tolower(c))  { */
  785. /* #else */
  786.             switch(c) {
  787. /* #endif */
  788.             case ('T'):
  789.             case ('t'):
  790.                 ++tflag;
  791.                 break;
  792.             case ('V'):
  793.             case ('v'):
  794.                 ++vflag;
  795.                 break;
  796.             case ('C'):
  797.             case ('c'):
  798.                 ++cflag;
  799. #ifdef EBCDIC
  800.                 ++aflag;       /* This is so you can read it on the screen */
  801. #endif                         /*  A.B.  03/24/90                          */
  802.                 break;
  803.             case ('A'):
  804.             case ('a'):
  805.                 ++aflag;
  806.                 break;
  807.         case ('M'):        /* map filename flag v2.0j */
  808.         case ('m'):
  809.         ++mflag;
  810.         break;
  811.             default:
  812.                 usage();
  813.                 break;
  814.             }
  815.         }
  816.     }
  817. /*  I removed the filter for the a and c flags so they could be used together */
  818. /*  Especially on EBCDIC based systems where you would want to read the text  */
  819. /*  on the screen.  Allan Bjorklund.  03/24/90                                */
  820.  
  821.     if ((tflag && vflag) || (tflag && cflag) || (vflag && cflag) ||
  822.         (tflag && aflag) || (aflag && vflag))
  823.  
  824.     {
  825.         fprintf(stderr, "only one of -t, -c, -a, or -v\n");
  826.         exit(1);
  827.     }
  828.     if (argc-- == 0)
  829.         usage();
  830.  
  831.     /* .ZIP default if none provided by user */
  832.     strcpy(zipfn, *argv++);
  833. /* v2.0b This doesn't permit paths like "..\dir\filename" */
  834.  
  835. #ifdef REALOLDSTUFF        /* v3.02 */
  836. #ifdef OLDSTUF
  837.     if (strchr(zipfn, '.') == NULL)
  838.         strcat(zipfn, ZSUFX);
  839. #else    /* v2.0b New code */
  840.  
  841.     c = strlen(zipfn);
  842.     if ( (c < 5)                             /* less than x.zip */
  843.       || (strcmp (&zipfn[c-4], ZSUFX) != 0)) /* v2.0b type doesn't
  844.                                               * match */
  845.         strcat (zipfn, ZSUFX);
  846. #endif
  847. #else                /* v3.02 */
  848. #ifdef    AMIGA
  849.     c = strlen(zipfn);
  850.     if ( (c < 5)                             /* less than x.zip */
  851.       || (stricmp (&zipfn[c-4], ZSUFX) != 0)) /* case-insensitive */
  852.         strcat (zipfn, ZSUFX);
  853. #else
  854.       /*
  855.        * OK, first check to see if the name is as given.  If it is
  856.        * found as given, then we don't need to bother adding the
  857.        * ZSUFX.  If it isn't found, then add the ZSUFX.  We don't
  858.        * check to see if this results in a good name, but that check
  859.        * will be done later.
  860.        */
  861.     if(stat (zipfn, &statbuf))        /* v3.02 */
  862.         strcat (zipfn, ZSUFX);        /* v3.02 */
  863. #endif    /* AMIGA */
  864.  
  865. #endif    /* not REALOLDSTUF */
  866.       
  867.     /* if any member file specs on command line, set filename
  868.        pointer to point to them. */
  869.  
  870.     if (argc != 0)
  871.         fnv = argv;
  872.  
  873.         /* allocate i/o buffers */
  874.     inbuf = (byte *) (malloc(INBUFSIZ));
  875.     outbuf = (byte *) (malloc(OUTBUFSIZ));
  876.  
  877.     /* v2.0g Hacked Allan's code.  No need allocating an ascebc
  878.      * scratch buffer unless we're doing translation.
  879.      */
  880.  
  881.     if(aflag)                           /* we need an ascebc scratch v2.0g */
  882.         outout = (byte *) (malloc(OUTBUFSIZ)); /* ..so allocate it v2.0g */
  883.     else
  884.         outout = outbuf;                /* just point to outbuf v2.0g */
  885.  
  886.     if ((inbuf == NULL) || (outbuf == NULL) || (outout == NULL)) {  /* v2.0g */
  887.         fprintf(stderr, "Can't allocate buffers!\n");
  888.         exit(1);
  889.     }
  890.  
  891.     /* do the job... */
  892.     process_zipfile();
  893.     exit(0);
  894. }
  895.  
  896.